<template>
  <w-dialog :border="false" closeFree width="65vw" @ok="selectOk" @cancel="close" :title="title" v-model="visible">
    <div class="picker">
      <div class="candidate" v-loading="loading">
        <el-row :gutter="20">
          <el-col :span="24" :xs="24">
            <el-form :model="queryParams" ref="queryForm" :inline="true" v-show="showSearch">
              <el-form-item v-if="isLazy" label="公司名称" prop="selectedRemoteCompany">
                <el-select
                  v-model="selectedRemoteCompany"
                  filterable
                  remote
                  :loading="remoteLoading"
                  reserve-keyword
                  placeholder="请输入公司名称进行过滤"
                  :remote-method="remoteSearchCompanyList"
                  style="width: 240px"
                  clearable
                >
                  <el-option v-for="item in remoteCompanyList" :key="item.companyId" :label="item.companyName" :value="item.companyId">
                    <span style="float: left">{{ item.companyName }}</span>
                    <span style="float: right; margin-left: 20px; color: var(--el-text-color-secondary); font-size: 13px;">{{ item.parentName }}</span>
                  </el-option>
                </el-select>
              </el-form-item>
              <el-form-item v-else label="公司名称" prop="companyName">
                <el-input
                  v-model="queryParams.companyName"
                  placeholder="请输入公司名称"
                  clearable
                  size="default"
                  @keyup.enter="handleQuery"
                />
              </el-form-item>
              <el-form-item v-if="!isLazy">
                <search-button @click="handleQuery" />
                <reset-button @click="resetQuery" />
              </el-form-item>
            </el-form>
            <el-table
              v-if="isLazy"
              :row-key="getRowKey"
              lazy
              :load="lazyLoad"
              v-loading="loading"
              :data="companyList"
              :tree-props="{ children: 'child'}"
              ref="multipleTable"
              @select="onSelect"
              @select-all="onSelectAll"
              @row-click="handleCurrent"
            >
              <el-table-column
                v-if="!isRadio"
                type="selection"
                width="55"
                align="center"
              />
              <el-table-column prop="companyName" label="公司名称" min-width="180" />
              <el-table-column prop="companyCode" label="公司编码" min-width="80" />
              <el-table-column prop="companyShortname" label="简称" min-width="120" />
            </el-table>
            <el-table
              v-else
              :row-key="getRowKey"
              v-loading="loading"
              :data="companyList"
              default-expand-all
              :tree-props="{ children: 'child', hasChildren: 'hasChildren' }"
              ref="multipleTable"
              @select="onSelect"
              @select-all="onSelectAll"
              @row-click="handleCurrent"
            >
              <el-table-column
                v-if="!isRadio"
                type="selection"
                width="55"
                align="center"
              />
              <el-table-column prop="companyName" label="公司名称" min-width="180" />
              <el-table-column prop="companyCode" label="公司编码" min-width="80" />
              <el-table-column prop="companyShortname" label="简称" min-width="120" />
            </el-table>
          </el-col>
        </el-row>
      </div>
      <div class="selected">
        <div class="count">
          <span>已选 {{ select.length }} 项</span>
          <span @click="clearSelected">清空</span>
        </div>
        <div class="org-items" style="height: 350px">
          <el-empty
            :image-size="100"
            description="请点击左侧列表选择数据"
            v-show="select.length === 0"
          />
          <div v-for="(org, index) in select" :key="index" class="org-item">
            <div>
              <i class="el-icon-folder-opened"></i>
              <span style="position: static" class="name">{{ org.companyName }}</span>
            </div>
            <i class="el-icon-close" @click="noSelected(org, index)"></i>
          </div>
        </div>
      </div>
    </div>
  </w-dialog>
</template>

<script>
import { listCompany, companyListByParentId, remoteSearchCompanyList } from './companyName'
import 'vue3-treeselect/dist/vue3-treeselect.css'
import { debounceWrapper } from '@/utils/zmids'

export default {
  name: 'OrgPicker',
  components: {},
  props: {
    title: {
      default: '请选择',
      type: String
    },
    type: {
      default: 'org', //org选择部门/人员  user-选人  dept-选部门 role-选角色
      type: String
    },
    isRadio: {
      default: false,
      type: Boolean
    },
    selected: {
      default: () => {
        return []
      },
      type: Array
    },
    isLazy: {
      default: false,
      type: Boolean
    },
    rootCompanyId: {
      default: '0',
      type: String
    }
  },
  emits: ['ok'],
  data() {
    const isLoginNameExistRule = (rule, value, callback) => {
      if (this.form.userId === undefined && value) {
        isLoginNameExist(value).then((response) => {
          if (response.data === true) {
            callback('登录名已存在')
          } else {
            callback()
          }
        })
      } else {
        // 编辑的时候不校验
        callback()
      }
    }
    return {
      visible: false,
      checkAll: false,
      nodes: [],
      select: [],
      search: '',
      deptStack: [],

      selectOption: undefined,
      // 遮罩层
      loading: true,
      // 远程搜索loading
      remoteLoading: false,
      // 显示搜索条件
      showSearch: true,
      // 总条数
      total: 0,
      // 表格树数据
      companyList: [],
      // 机构树选项
      orgOptions: [],
      // 是否显示弹出层
      open: false,
      // 查询参数
      queryParams: {
        companyId: undefined,
        companyName: undefined,
        status: undefined
      },
      // 表单参数
      form: {},
      // 表单校验
      rules: {
        companyName: [{ required: true, message: '公司名称不能为空', trigger: 'blur' }],
        companyCode: [{ required: true, message: '公司编码不能为空', trigger: 'blur' }],
        orderNum: [{ required: true, message: '菜单顺序不能为空', trigger: 'blur' }],
        email: [
          {
            type: 'email',
            message: "'请输入正确的邮箱地址",
            trigger: ['blur', 'change']
          }
        ]
      },
      // 被选中的公司id
      selectedRemoteCompany: undefined,
      // 远程搜索公司列表
      remoteCompanyList: []
    }
  },
  watch: {
    // 根据名称筛选部门树
    companyName(val) {
      this.$refs.tree.filter(val)
    },
    // 根据被选中公司筛选公司树
    selectedRemoteCompany(val) {
      if (val) {
        companyListByParentId(val).then((response) => {
          this.companyList = []
          this.companyList = response.data.map(item=> {
            return {
              ...item,
              hasChildren: true
            }
          })
        })
        setTimeout(() => {
          this.traverse(this.select, this.companyList, true)
        }, 200)
      } else {
        companyListByParentId(this.rootCompanyId).then((response) => {
          this.companyList = []
          this.companyList = response.data.map(item=> {
            return {
              ...item,
              hasChildren: true
            }
          })
          setTimeout(() => {
            this.traverse(this.select, this.companyList, true)
          }, 200)
          this.resetQuery()
        })
      }
    }
  },
  created() {
    this.getList()
  },
  methods: {
    getRowKey(row) {
      return row.companyId
    },
    show() {
      this.visible = true
      this.init()
    },

    noSelected(org, index) {
      this.select.forEach((item) => {
        if (item.companyId == org.companyId) {
          this.$refs.multipleTable.toggleRowSelection(item, false)
        }
      })
      this.select.splice(index, 1)
    },
    // 多选操作
    onSelect(selection, row){
      if (!this.isRadio) {
        const {companyId} = row
        const index = this.select.findIndex(i => i.companyId === companyId)
        // 如果已经包含该项 说明本次是取消勾选
        if (index > -1) {
          this.select.splice(index, 1)
        } else {
          // 否则，将已勾选的push进去
          this.select.push(row)
        }
      }
    },
    // 全选操作
    onSelectAll(selection) {
      if (!this.isRadio) {
        // 如果select中含有当前页所有数据，说明是取消全选，否则就是全选
        const companys = this.getAllCompanyList(this.companyList)
        const companyIds = companys.map((item) => item.companyId)
        const selectedList = this.select.filter(row => companyIds.includes(row.companyId))
        // 说明当前页所有数据已选中，此时操作为取消全选
        if (selectedList && selectedList.length === companys.length) {
          // 删除当前页面的数据
          this.traverse(this.select, this.companyList, false)
          this.select = this.select.filter(row => !companyIds.includes(row.companyId))
        } else {
          // 重新添加当前页被选中的数据
          this.select = this.select.filter(row => !companyIds.includes(row.companyId))
          this.select.push(...companys)
          this.traverse(this.select, this.companyList, true)
        }
        this.ids = selection.map((item) => item.companyId)
        this.single = selection.length != 1
        this.multiple = !selection.length
      }
    },
    getAllCompanyList(companyList){
      let companys = [];
      companyList.forEach((item) => {
        companys.push(item); // 添加当前节点的 companyId
        // 递归获取子节点的 companyId
        if (item.child && item.child.length > 0) {
          companys = companys.concat(this.getAllCompanyList(item.child));
        }
      });
      return companys;
    },
    handleCurrent(row) {
      //row就是行信息
      if (this.isRadio) {
        this.select = [row]
        this.ids = row.companyId
        // this.$refs.multipleTable.toggleRowSelection(row) // 传入行信息，使得该行复选框打上勾
      }
    },
    recover() {
      this.$refs.multipleTable.clearSelection()
      this.select = []
    },
    selectOk() {
      this.$emit(
        'ok',
        Object.assign(
          [],
          this.select.map((v) => {
            v.avatar = undefined
            return v
          })
        )
      )
      this.visible = false
      this.recover()
    },
    clearSelected() {
      this.$confirm('您确定要清空已选中的项?', '提示', {
        confirmButtonText: '确定',
        cancelButtonText: '取消',
        type: 'warning'
      }).then(() => {
        this.recover()
      })
    },
    close() {
      this.selectedRemoteCompany = undefined
      this.$emit('close')
      this.recover()
    },
    init() {
      this.checkAll = false
      this.deptStack = []
      this.nodes = []
      this.select = Object.assign([], this.selected)
      setTimeout(() => {
        this.traverse(this.select, this.companyList, true)
      }, 200)
    },
    // 回显勾选
    traverse(select, companyList, isSelect){
      const companyIds = select.map(item => item.companyId)
      companyList.forEach((item) => {
        if (companyIds.includes(item.companyId)) {
          this.$refs.multipleTable.toggleRowSelection(item, isSelect);
        }

        // 递归处理 child
        if (item.child && item.child.length > 0) {
          this.traverse(select, item.child, isSelect);
        }
      });
    },
    // 递归修改列表的children属性名
    traverseChild(companyList){
      companyList.forEach(item => {
        if (item.children && item.children.length > 0) {
          this.traverseChild(item.children)
        }
        item.child = item.children
        delete item.children
      })
    },
    /** 查询部门列表 */
    getList: debounceWrapper(function () {
      this.loading = true
      this.queryParams.companyId = this.selectOption && this.selectOption.companyId
      if(this.isLazy){
        companyListByParentId(this.rootCompanyId).then((response) => {
          this.companyList = response.data.map(item=> {
            return {
              ...item,
              hasChildren: true
            }
          })
          this.$nextTick(() => {
            // 比较select列表，进行多选回显
            this.traverse(this.select, this.companyList, true)
          })
          this.loading = false
        })
      }else{
        listCompany(this.queryParams).then((response) => {
          this.companyList = this.handleTree(response.data, 'companyId')
          this.traverseChild(this.companyList)
          this.$nextTick(() => {
            // 比较select列表，进行多选回显
            this.traverse(this.select, this.companyList, true)
          })
          this.loading = false
        })
      }
    }),
    remoteSearchCompanyList(value) {
      if (value) {
        this.remoteLoading = true;
        setTimeout(() => {
          remoteSearchCompanyList(value).then(res => {
            this.remoteCompanyList = res.data;
            this.remoteLoading = false;
          })
        }, 200);
      } else {
        this.remoteCompanyList = [];
        this.selectedRemoteCompany = undefined;
      }
    },
    /** 搜索按钮操作 */
    handleQuery() {
      this.getList()
    },
    /** 重置按钮操作 */
    resetQuery() {
      this.selectOption = undefined
      this.resetForm('queryForm')
      if (this.selectedRemoteCompany){
        this.selectedRemoteCompany = undefined
      }
      this.handleQuery()
    },
    // 取消按钮
    cancel() {
      this.open = false
      this.reset()
    },
    // 表单重置
    reset() {
      this.form = {
        companyId: undefined,
        companyName: undefined,
        companyCode: undefined,
        companyShortname: undefined,
        orderNum: 1,
        leader: undefined,
        email: undefined,
        deptType: '1',
        deptLevel: '0',
        status: 'Y',
      }
      this.resetForm('form')
    },
    async lazyLoad(row, node, resolve){
      return companyListByParentId(row.companyId).then((response) => {
        const data = response.data.map((item)=>{
          return {
            ...item,
            hasChildren: true
          }
        })
        this.traverseChild(data)
        resolve(data)
        // 递归遍历deptList，找到deptId=row.deptId那一个值，将data作为child放入deptList
        this.updateDeptChildren(this.companyList, row.companyId, data)
        this.$nextTick(() => {
          // 比较select列表，进行多选回显
          this.traverse(this.select, this.companyList, true)
        })
      })
    },
    updateDeptChildren(companyList, companyId, data) {
      companyList.forEach((item) => {
        if (item.companyId === companyId) {
          // 找到匹配的 deptId，更新 child
          item.child = data;
        } else if (item.child && item.child.length > 0) {
          // 递归查找子节点
          this.updateDeptChildren(item.child, companyId, data);
        }
      });
    }
  }
}
</script>

<style lang="less" scoped>
.candidate,
.selected {
  position: absolute;
  display: inline-block;
  height: 400px;
  border: 1px solid #e8e8e8;
}

.picker {
  height: 402px;
  position: relative;
  text-align: left;
  .candidate {
    left: 0;
    top: 0;
    width: 70%;

    & > div:first-child {
      padding: 5px 10px;
    }
  }

  .selected {
    right: 0;
    top: 0;
    width: 30%;
  }

  .org-items {
    overflow-y: auto;
    height: 310px;

    .el-icon-close {
      position: absolute;
      right: 5px;
      cursor: pointer;
      font-size: larger;
    }

    .org-role-item {
      display: flex;
      align-items: center;
      padding: 10px 5px;
    }

    :deep(.org-user-item)  {
      display: flex;
      align-items: center;
      padding: 5px;

      & > div {
        display: inline-block;
      }

      .avatar {
        width: 35px;
        text-align: center;
        line-height: 35px;
        background: #1890ff;
        color: white;
        border-radius: 50%;
      }
    }

    :deep(.org-item) {
      margin: 0 5px;
      border-radius: 5px;
      padding: 10px 5px;
      display: flex;
      .el-checkbox {
        margin-right: 10px;
      }

      .name {
        margin-left: 5px;
      }

      &:hover {
        background: #f1f1f1;
      }
    }
  }
}

.selected {
  border-left: none;
  .count {
    width: 100%;
    padding: 10px;
    display: inline-block;
    border-bottom: 1px solid #e8e8e8;
    margin-bottom: 5px;
    & > span:nth-child(2) {
      float: right;
      color: #c75450;
      cursor: pointer;
    }
  }
}

:deep(.el-dialog__body) {
  padding: 10px 20px;
}

.disabled {
  cursor: not-allowed !important;
  color: #8c8c8c !important;
}

::-webkit-scrollbar {
  float: right;
  width: 4px;
  height: 4px;
  background-color: white;
}

::-webkit-scrollbar-thumb {
  border-radius: 16px;
  background-color: #efefef;
}

:deep(.el-table) {
  height: calc(400px - 100px);
}
:deep(.el-table__body-wrapper) {
  height: calc(100% - 50px);
  overflow-y: auto;
  overflow-x: hidden;
}
:deep(.el-pagination) {
  float: right;
}
</style>
